package com.cargohu.aishouyu.file.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.amazonaws.services.s3.model.S3Object;
import com.cargohu.aishouyu.file.dto.FileAddDTO;
import com.cargohu.aishouyu.file.dto.FileUpdateDTO;
import com.cargohu.aishouyu.file.entity.File;
import com.cargohu.aishouyu.file.mapper.FileMapper;
import com.cargohu.aishouyu.file.oss.OssProperties;
import com.cargohu.aishouyu.file.oss.service.OssTemplate;
import com.cargohu.aishouyu.file.req.FileRequest;
import com.cargohu.aishouyu.file.resp.FileDetailVo;
import com.cargohu.aishouyu.file.resp.FileResponse;
import com.cargohu.aishouyu.file.service.FileService;
import com.cargohu.aishouyu.framework.exception.BusinessException;
import com.cargohu.aishouyu.framework.page.OrderByItem;
import com.cargohu.aishouyu.framework.page.Paging;
import com.cargohu.aishouyu.framework.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件管理表 服务实现类
 *
 * @author aaron.wang
 * @since 2024-01-07
 */
@Slf4j
@Service
public class FileServiceImpl extends BaseServiceImpl<FileMapper, File> implements FileService {

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private OssProperties ossProperties;

    @Autowired
    private OssTemplate minioTemplate;

    @Value("${file.url}")
    private String fileUrl;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addFile(FileAddDTO fileAddDTO) throws Exception {
        File file = new File();
        BeanUtils.copyProperties(fileAddDTO, file);
        return save(file);

    }

    @Override
    public Map<String, String> uploadFile(MultipartFile file) {
        String fileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
        Map<String, String> resultMap = new HashMap<>(4);
        resultMap.put("bucketName", ossProperties.getBucketName());
        resultMap.put("fileName", fileName);
        resultMap.put("url", String.format(fileUrl + "/file/%s/%s", ossProperties.getBucketName(), fileName));

        try {
            minioTemplate.putObject(ossProperties.getBucketName(), fileName, file.getInputStream());
            // 文件管理数据记录,收集管理追踪文件
            fileLog(file, fileName);
        } catch (Exception e) {
            log.error("上传失败", e);
            throw new BusinessException("文件上传失败");
        }
        return resultMap;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateFile(FileUpdateDTO fileUpdateDTO) throws Exception {
        Long id = fileUpdateDTO.getId();
        File file = getById(id);
        if (file == null) {
            throw new BusinessException("文件管理表不存在");
        }
        BeanUtils.copyProperties(fileUpdateDTO, file);
        file.setUpdateTime(new Date());
        return updateById(file);

    }

    @Override
    public void getFile(String bucket, String fileName, HttpServletResponse response) {
        try (S3Object s3Object = minioTemplate.getObject(bucket, fileName)) {
            response.setContentType("application/octet-stream; charset=UTF-8");
            IoUtil.copy(s3Object.getObjectContent(), response.getOutputStream());
        } catch (Exception e) {
            log.error("文件读取异常: {}", e.getLocalizedMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteFile(Long id) throws Exception {
        return removeById(id);

    }

    @Override
    public FileDetailVo getFileById(Long id) throws Exception {
        return fileMapper.getFileById(id);


    }

    @Override
    public Paging<FileResponse> getFileList(FileRequest fileRequest) throws Exception {
        handlePage(fileRequest, OrderByItem.desc("id"));
        List<FileResponse> list = fileMapper.getFileList(fileRequest);
        Paging<FileResponse> paging = new Paging<>(list);
        return paging;
    }


    /**
     * 文件管理数据记录,收集管理追踪文件
     *
     * @param file     上传文件格式
     * @param fileName 文件名
     */
    private void fileLog(MultipartFile file, String fileName) {
        File sysFile = new File();
        sysFile.setFileName(fileName);
        sysFile.setOriginal(file.getOriginalFilename());
        sysFile.setFileSize(file.getSize());
        sysFile.setType(FileUtil.extName(file.getOriginalFilename()));
        sysFile.setBucketName(ossProperties.getBucketName());
        this.save(sysFile);
    }
}
